package com.oneinlet.config;

import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.MalformedJsonException;
import com.oneinlet.YCString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;


/**
 * Created by WangZiHe on 2017/11/5
 * QQ/WeChat:648830605
 * QQ-Group:368512253
 * Blog:www.520code.net
 * Github:https://github.com/yancheng199287
 */


public class JsonMethodArgumentResolver implements HandlerMethodArgumentResolver {

    private Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").setPrettyPrinting().create();
    private JsonReader reader;
    private JsonParser jsonParser = new JsonParser();
    private Logger logger = LoggerFactory.getLogger(JsonMethodArgumentResolver.class);


    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return true;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        String contentType = request.getContentType();
        if (YCString.INSTANCE.isEmpty(contentType) || !request.getContentType().contains("application/json")) {
            return null;
        }
        ServletInputStream inputStream = request.getInputStream();
        if (!inputStream.isFinished()) {
            reader = new JsonReader(new InputStreamReader(inputStream));
        }

        try {
            Class<?> parameterType = methodParameter.getParameterType();
            String parameterName = methodParameter.getParameterName();
            JsonObject jsonObject = jsonParser.parse(reader).getAsJsonObject();
            logger.info(jsonObject.toString());
            if (jsonObject.get(methodParameter.getParameterName()) == null) {
                return null;
            }
            if (jsonObject.get(methodParameter.getParameterName()).isJsonObject()) {
                JsonObject nodeJsonObject = jsonObject.getAsJsonObject(parameterName);
                if (nodeJsonObject != null) {
                    return gson.fromJson(nodeJsonObject.toString(), parameterType);
                }
            } else if (jsonObject.get(parameterName).isJsonPrimitive()) {
                if (parameterType.isAssignableFrom(Integer.class)) {
                    return jsonObject.get(parameterName).getAsInt();
                } else if (parameterType.isAssignableFrom(Double.class)) {
                    return jsonObject.get(parameterName).getAsDouble();
                } else if (parameterType.isAssignableFrom(String.class)) {
                    return jsonObject.get(parameterName).getAsString();
                } else if (parameterType.isAssignableFrom(BigDecimal.class)) {
                    return jsonObject.get(parameterName).getAsBigDecimal();
                } else if (parameterType.isAssignableFrom(Number.class)) {
                    return jsonObject.get(parameterName).getAsNumber();
                }
            } else if (jsonObject.get(parameterName).isJsonArray()) {
                JsonArray nodeJsonObject = jsonObject.getAsJsonArray(parameterName);
                return gson.fromJson(nodeJsonObject.toString(), parameterType);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("解析json数据发生错误", e);
            throw new MalformedJsonException("解析json数据发生错误,可能是json格式错误或者参数无法匹配");
        }
        return null;
    }


}
